<?php
class TbfSecurity {
    //密码验证
    //func (plain string,hashed string)bool
    static function PasswordVerify($plain,$hashed){
        return crypt($plain,$hashed)===$hashed;
    }
    //hash密码
    //func (plain string)(hashed string)
    static function PasswordGenerate($plain){
        $salt = bin2hex(TbfRand::SecurityBinary(12));
        $hashed = crypt($plain,'$2a$10$'.$salt.'$');
        return $hashed;
    }

    //POST请求完全不被跨域的网站,的csrf防御方法,返回false的时候表示发生了csrf
    //会修改数据的方法请全部使用POST请求.
    static function isNoCrossDomainCsrfSafe(){
        if ($_SERVER['REQUEST_METHOD'] === 'GET'){
            return true;
        }
        //检查refer
        $hostUrl = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'];
        $refer = '';
        if (!empty($_SERVER['HTTP_REFERER'])){
            $refer = $_SERVER['HTTP_REFERER'];
        }
        if ($refer===$hostUrl || strpos($refer,$hostUrl.'/')===0){
            return true;
        }
        $origin = '';
        if (!empty($_SERVER['HTTP_ORIGIN'])){
            $origin = $_SERVER['HTTP_ORIGIN'];
        }
        if ($origin===$hostUrl){
            return true;
        }
        return false;
    }

    // https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#RULE_.231_-_HTML_Escape_Before_Inserting_Untrusted_Data_into_HTML_Element_Content
    // rule #1 #2
    static function XssHtmlBody($s){
        return str_replace(array("\0",'&','<','>','"',"'",'+',' '),
            array('&#xfffd;','&amp;','&lt;','&gt;','&#34;','&#39;','&#43;','&nbsp;'),(string)$s);
    }
    //rule #3
    //正常的json_encode,但是替换 < 为 \u003c
    static function XssJson($obj){
        $s = json_encode($obj);
        return str_replace('<','\u003c',$s);
    }
    //rule #5
    //除了字母和数字,全部进行url转义,按照字节进行转义就可以了.
    static function XssUrlParamValue($s){
        $s = (string)$s;
        $output = '';
        for($i=0;$i<strlen($s);$i++){
            $ci = ord($s[$i]);
            if (($ci>=ord('0') && $ci<=ord('9')) ||
                ($ci>=ord('A') && $ci<=ord('Z')) ||
                ($ci>=ord('a') && $ci<=ord('z')) ){
                $output .= chr($ci);
            }else{
                $output .= '%'.dechex($ci);
            }
        }
        return $output;
    }
    //适用于左右没有打引号的属性值
    //rule #2
    //除了字母和数字,全部进行html转义,,打引号的属性值,可以直接使用XssHtmlBody
    /*
    static function XssHtmlAttributeValue($s){
        $codeArray = TbfString::Utf8ToIntArray($s);
        $output = '';
        foreach($codeArray as $c){
            if (($c>=ord('0') && $c<=ord('9')) ||
                ($c>=ord('A') && $c<=ord('Z')) ||
                ($c>=ord('a') && $c<=ord('z')) ){
                $output .= chr($c);
            }else{
                $output .= '&#'.$c.';';
            }
        }
        return $output;
    }
    */
}
